﻿using System;
using Filtry.Data;
using Filtry.Utilities;

namespace Filtry.Logic
{
    public static class Noise
    {
        public static GrayscaleImage GaussianNoise(this GrayscaleImage image, double deviation)
        {
            GrayscaleImage newImage = image.Clone();
            var random = new Random();

            byte[] pixels = newImage.GetAllPixels();
            for (int index = 0; index < pixels.Length; index++)
            {
                double randomNumber = random.NextNormalDouble(deviation, 0);
                double value = Math.Max(Math.Min(byte.MaxValue, randomNumber + pixels[index]), byte.MinValue);
                pixels[index] = (byte)value;
            }
            return newImage;
        }

        public static GrayscaleImage ShotNoise(this GrayscaleImage image, double lambda)
        {
            GrayscaleImage newImage = image.Clone();
            var random = new Random();

            byte[] pixels = newImage.GetAllPixels();
            for (int index = 0; index < pixels.Length; index++)
            {
                double randomNumber = random.NextLaplaceDouble(lambda, 0);
                double value = Math.Max(Math.Min(byte.MaxValue, randomNumber + pixels[index]), byte.MinValue);
                pixels[index] = (byte)value;
            }
            return newImage;
        }

        public static GrayscaleImage SaltAndPepperNoise(this GrayscaleImage image, double intensityPercent,
                                                        double whitePercent = 0.5)
        {
            GrayscaleImage newImage = image.Clone();
            var random = new Random();
            byte[] pixels = newImage.GetAllPixels();
            for (int index = 0; index < pixels.Length; index++)
            {
                if (random.NextDouble() < intensityPercent)
                {
                    if (random.NextDouble() < whitePercent)
                    {
                        pixels[index] = byte.MaxValue;
                    }
                    else
                    {
                        pixels[index] = byte.MinValue;
                    }
                }
            }
            return newImage;
        }
    }
}